מבוא למדעי ה מחשב הרצאה 4: משפטים, תנאים ולולאות מבוסס על השקפים שנערכו במקור ע"י שי ארצי, גיתית רוקנשטיין, איתן אביאור, וסאהר אסמיר, ועובדו ע"י מיכאל אלעד בסמסטר חורף 2007. תוכנ י יה משפטים בשפת - C (Statements) משפטי תנאי משפט תנאי if-else פסוק ברירה switch-case-default פעולת התנאי:? לולאות for while דוגמאות: מציאת GCD (אלגוריתם אוקלידס) מציאת שורש (שיטת ניוטון-רפסון) 2 1
Statements - משפטים בשפת C משפט ביטוי statement) :(expression ביטוי שאחריו ';' נחשב כמשפט. לעיתים קיימות תוצאות לוואי למשפט כזה ולעיתים לא. ;++y x = ; משפט ריק statement) :(empty מורכב מ- ';' בלבד. אין למשפט תוצאות לוואי. משפט מורכב statement) :(compound רצף משפטים המוקפים בסוגריים מסולסלים { נחשב כמשפט אחד. רצף { כזה נקרא גם בלוק. t = x; x = y; y = t; 3 תוכנ י יה משפטים בשפת - C (Statements) משפטי תנאי משפט תנאי if-else פסוק ברירה switch-case-default פעולת התנאי:? לולאות for while דוגמאות: מציאת GCD (אלגוריתם אוקלידס) מציאת שורש (שיטת ניוטון-רפסון) 4 2
משפט if expression 0 Statement 0 זהו משפט מהצורה: אם ערך האמת של expression הינו,True מבצעים את.statement אם ערך האמת של expression הינו,False מדלגים על ביצוע statement (ועוברים למשפט הבא אחריו). לרוב, statement יה יה משפט מורכב. לדוגמה: if (expression) statement if(b*b < 4*a*c) { printf( no real solution to the quad. equation.\n ); return 0; 5 משפט if-else expression 0 0 if (expression) statement1 else statement2 זהו משפט מהצורה: אם ערך האמת של expression הינו,True מבצעים את statement1 מדלגים על statement2 ועוברים למשפט הבא. אם ערך האמת של expression הינו,False מדלגים על,statement1 מבצעים את statement2 ואז ממשיכים לבא. לדוגמה: st1 st2 if(tomorrow_is_rainy == y ) printf( Take your umbrella.\n"); else printf( Leave the umbrella at home.\n"); 6 3
ק ינ ו ן if-else מה מבצע המשפט הבא? if(a==1) if(b==2) if(b==2) printf("***"); printf("***"); else else printf("###"); printf("###"); b =2 2 a =1 *** ### 1 ### ### if(a==1) { if(b==2) printf("***"); else printf("###"); ה- else מקושר תמיד ל- if האחרון. ניתן להפריד ביניהם באמצעות {... 7 רב ברירה if-else if ( a < 0 ) return -1; else if ( a == 0 ) return 0; else if ( a < 11 ) return 1; else return a; False False False a == 0 a < 11 True a < 0 True 0 True -1-1 0 1 a a 10 1 a 8 4
רב ברירה if-else if ( a < 0 ) return -1; else if ( a == 0 ) return 0; else if ( a < 11 ) return 1; else return a; if ( a < 0 ) return -1; else if ( a == 0 ) return 0; else if ( a < 11 ) return 1; else return a; 9 משפטי switch-case-default switch (expression) { case value1: statement1 break; //optional... default: //optional statementn זהו משפט מהצורה: טיפוס שלם קבוע שלם הערך של expression מושווה לכל.value בהתאמה הראשונה שנמצאת, מתבצע ה- statement המתאים לאותו.value אם ה- statement מכיל break אז מדלגים מה- break לפקודה הבאה (אחרי ה- switch ). אחרת, ממשיכים לבצע את הבדיקות עפ"י ה- value הבאים ובהתאם לחשב את ה- statement המתאים. אם אין אף התאמה ויש default מתבצע ה- statement המתאים. 10 5
משפטי switch-case-default int x, y, res; char op; RUN... // read x, y, op switch (op) { case '+': printf("result is: %d", x + y); break; //what if we remove it? case '-': printf("result is: %d", x - y); break;... // code for '*' and '/ default: printf("invalid op! ); 11 ביטו י י תנא י :? זהו משפט מהצורה: expression1? expression2 : expression3 אם ערך האמת של expression1 הינו,True משערכים את expression2 וזהו גם הערך של הביטוי. אם ערך האמת של expression1 הינו,False משערכים את expression3 וזהו גם הערך של הביטוי. לדוגמה: d = (a > b)? (a b) : (b a); min = (x < y)? x : y; = a-b = min(x,y) 12 6
תוכנ י יה משפטים בשפת - C (Statements) משפטי תנאי משפט תנאי if-else פסוק ברירה switch-case-default פעולת התנאי:? לולאות for while דוגמאות: מציאת GCD (אלגוריתם אוקלידס) מציאת שורש (שיטת ניוטון-רפסון) 13 לולא ות קטע קוד המתבצע מספר פעמים נקרא לולאה.(loop) מספר הפעמים תלוי בערכו של ביטוי המחושב במהלך ריצת התכנית. כל אחד מביצועי הלולאה נקרא איטרציה.(iteration) ב- C קיימים שלושה משפטים המאפשרים ביצוע לולאות: while statement for statement do-while statement 14 7
לולאת while expression 0 statement 0 זהו משפט מהצורה: while (expression) statement כל עוד ערך האמת של expression הינו.statement מבצעים את,True לדוגמה, חישוב עצרת: unsigned int n, factorial = 1, i = 2; scanf( %d, &n); while(i <= n) { factorial = factorial * i; factorial *= i++; i = i + 1; printf("n!= %d", factorial); 15 דוגמה: חישוב ממוצע זוגי ים וממ וצע א י-זוג י ים קלט: סדרה של מספרים שלמים שהאחרון בהם הוא 0. פלט: ממוצע המספרים הזוגיים בסדרה (לא כולל 0) וממוצע המספרים האי-זוגיים. הנחות: קלט חוקי, יש לפחות שלם אחד זוגי ואחד אי-זוגי. אלגוריתם: חישוב סכום הזוגיים (אי-זוגיים) ומספרם באופן איטרטיבי (על ידי לולאה). בכל איטרציה נטפל בשלם אחד מהסדרה (אם הוא אינו 0). אם הוא זוגי (אי זוגי), נוסיפו לסכום הזוגיים (אי זוגיים) ונגדיל את מספר הזוגיים (אי- זוגיים) בהתאמה. 16 8
#include <stdio.h> int main() RUN { int odd_sum = 0, even_sum = 0, odd_count = 0, even_count = 0, next; printf("please insert a number\n"); scanf("%d", &next); while (next) { if (next % 2) { odd_sum += next; odd_count++; else { even_sum += next; even_count++; printf("please insert a number\n"); scanf("%d", &next); printf("\naverage of even numbers is %6.2f.\n" "Average of odd numbers is %6.2f.\n", (double)even_sum/even_count, (double)odd_sum/odd_count); return 0; 17 לולאת do-while statement do statement while(expression); זהו משפט מהצורה: 0 expression 0 מבצעים את statement כל עוד ערך האמת של expression הינו True (פעם אחת לפחות). לדוגמה, קליטת מספר חיובי: int x; do { printf("please enter a positive number: "); scanf("%d", &x); while (x <= 0); 18 9
לולאת for expression1 זהו משפט מהצורה: for(expression1;expression2;expression3) statement expression2 0 statement 0 מבצעים את expression1 (אתחול) ואז כל עוד ערך האמת של expression2 (תנאי) הינו,True מבצעים את statement ואז expression3 (קידום). כ"א משלושת הביטויים יכול להיות ריק. expression3 expression1 while (expression2) { statement expression3 שקול ל: 19 - המשך לולאת for sum = 0; for(i = 1; i <= n; i++) sum += i * i; : n i= 1 i 2 חישוב הביטוי for(i = 2 ; i <= n; i++) factorial *= i; חישוב עצרת: printf("n!= %d", factorial); i = 2; while(i <= n) { factorial *= i; i++; printf("n!= %d", factorial); השווה מול השימוש ב- while : 20 10
- המשך לולאת for שימוש באופרטור פסיק,: חישוב ביטוי מהצורה exp1, exp2 מתבצע ע"י חישוב exp1 ולאחריו חישוב.exp2 ערכו (טיפוסו) של ביטוי זה הינו ערכו (טיפוסו) של.exp2 sum = 0; for(i = 1; i <= n; i++) sum += i * i; קודם ראינו את התוכנית דר ך נוספת לביצוע הסכום הנ"ל: for(sum = 0, i = 1; i <= n; sum += i * i, i++); ככלל, בסוגריים הצמודים ל- for יופיעו ביטויים הקשורים בבקרת הלולאה (אך לא בתכנה), ולכן נעדיף את הפתרון הראשון שראינו. 21 תוכנ י יה משפטים בשפת - C (Statements) משפטי תנאי משפט תנאי if-else פסוק ברירה switch-case-default פעולת התנאי:? לולאות for while דוגמאות: מציאת GCD (אלגוריתם אוקלידס) מציאת שורש (שיטת ניוטון-רפסון) 22 11
מציאת המכנה המשותף הגדול ביותר (GCD).(Greatest Common Divider) מחלק משותף גדול ביותר :GCD בהינתן שני שלמים חיוביים m ו- n gcd(m,n) הוא השלם הגדול ביותר שמחלק את שניהם. פתרון ביה"ס יסודי: פרק את שני המספרים לגורמים ראשוניים. מכפלת הגורמים הראשוניים המשותפים היא ה- GCD. לדוגמא: n=270 m=700 n = 2 * 3 3 * 5 m = 2 2 * 5 2 * 7 gcd(700, 270) = 2 * 5 = 10 23 פיר ו ק מספר לגורמים ראשוני ים המשפט היסודי של האריתמטיקה קובע כי כל מס פר שלם יכול להיכתב בצורה ייח וד ית בתור מכפלה של מספרים ראשוניים. פירוק מספר n לגורמים: אם n ראשוני, הוסף את n לקבוצת המחלקים ועצור. אחרת, עבור סדרתית על המספרים הראשוניים עד שורש n. הוסף את p, המספר הראשוני הראשון המחלק את n, לקבוצת המחלקים וחזור על התהליך עם.n/p לדוגמה, עבור :n=30 5 = 5 * 5 3 = 15 * 15 2 = 30 קושי: האלגוריתם אינו מעשי עבור n גדול. למשל עבור מספר בן 18 ספרות יש צורך לעבור על כל הראשוניים עד 1,000,000,000 (השורש שלו!). מסיבה זו, פירוק לגורמים ראשוניים משמש בסיס לקריפטוגרפיה מודרנית. 24 12
אלגור יתם או יקל ידס לח ישוב GCD אלגוריתם אוקלידס מתבסס על הטענות המתמטיות הבאות:.r = m % n ואת n מחלק את q אם ורק אם n ואת m מחלק את q נובע מהשוויון.m = r + q * n עבור n השונה מ- 0 gcd(n,m%n).gcd(m,n) = m gcd(m, 0) = עבור m שאינו.0 מה קורה אם n? > m Euclid Aristotle Eudoxus of Cnidus 25 ההיג י ו ן הבסיס י נניח כי q הוא מחלק כלשהו המחלק באופן שלם הן את m והן את n. נניח כי.m>n m-2n m-n m n q ברור כי.gcd(m,n)=gcd(m-n,n) באופן דומה,,gcd(m,n)=gcd(m-2n,n) וכו'. למעשה, בהורדה כזו שוב ושוב נגיע לקשר:.gcd(m,n)=gcd(n,m%n) היפוך הסדר נובע מכך שבהכרח:.m%n<n 26 13
אלגור יתם או יקל ידס, דוגמאות דוגמא 1 דוגמא 2 m = q*n + r m n m n 700 = 2*270 + 160 270 = 1*160 + 110 160 = 1*110 + 50 110 = 2*50 + 10 50 = 5*10 + 0 700 270 270 160 160 110 110 50 50 10 10 0 100 17 17 15 15 2 2 1 1 0 27 אלגור יתם או יקל ידס, הוכחת נכונ ות נסמן ב- m i ו- n i את ערכי המשתנים m ו- n בתום האיטרציה ה- i. שמורה (תכונה שנשמרת במהלך האלגוריתם): gcd(m 0,n 0 ) = gcd(m i,n i ) הוכחת השמורה נעשית באינדוקציה על i: בסיס: מיידי. הנחה: ) i gcd(m 0,n 0 ) = gcd(m i,n צעד האינדוקציה: הנחת האינדוקציה טענה מתמטית אלגוריתם gcd(m i+1,n i+1 ) = gcd(n i,m i %n i ) = gcd(m i,n i ) = gcd(m 0,n 0 ) בתום האיטרציה האחרונה: gcd(m 0,n 0 ) = gcd(m N,n N ) = gcd(m N,0) = m N 28 14
אלגור יתם או יקל ידס, ק ידוד #include <stdio.h> RUN int main() { unsigned int m, n; scanf("%u%u", &n, &m); while(n!= 0) { unsigned int temp = n; n = m % n; m = temp; if(m!= 0) printf("the gcd is %d\n", m); return 0; 29 דוגמה: מציאת שורשי משוואה הגדרת הבעיה: חשב את נקודת החיתוך של פונקציה נתונה f(x) עם ה- 0, כלומר פתור,f(x)=0 עבור x ממשי. f(x) x אנו ניישם שיטה איטרטיבית לחיפוש הפתרון שיטת ניוטון רפסון. אנו נתחיל בנקודה x 0 וממנה נעדכן לנקודות המתקרבות לחציית הציר. 30 15
עקר ו ן הפע ולה נזכיר פיתוח לטור טיילור סביב נקודה: f ''( x) 2 f ( x+ δ) = f ( x) + f '( x) δ+ δ +... 2 לפונקציות "חלקות" ול- δ מספיק קטן, נקבל כי f ( x) f ( x+ δ ) = 0 δ = f(x) f '( x) x+δ x x 31 מציאת שור שים ב שיטת ניוטון-רפסון שיטת ניוטון-רפסון (Newton-Raphson) - שיטה למציאת שורש של פונקציה גזירה בתחום נתון ע"י קיזוז הסטייה שלה. נתוני עזר נדרשים: נקודה x 0 "קרובה" לשורש, ופונקצית הנגזרת של הפונקציה. x 0 32 16
שיטת ניוט ו ן-רפסו ן - המשך השיטה: חזור: עבור לנקודה שבה חותך המשיק (הנגזרת) את הציר האופקי x i+1 = x i - f(x i ) / f'(x i ) הנחה: הקטע איננו מכיל נקודות קיצון (שבהן הנגזרת מתאפסת) f(x 0 ) f(x 0 ) / (x 0 - x 1 ) = tan α = f'(x 0 ) x 1 x 0 33 שיטת ניוט ו ן-רפסו ן - הדגמה x 1 x 0 x x 3 2 34 17
שיטת ניוט ו ן-רפסו ן - תנאי עצירה x i+1 - x i < δ f(x i+1 ) < ε בפתרון שנראה, נשתמש במספר איטרציות מקסימלי כתנאי עצירה. שילוב התנאים δ ו- ε מושאר כתרגיל. < ε x i+1 x i < δ 35 ק וד מקור עבור הפ ונקצ יה f(x)=x 2 9- #include <stdio.h> #define MAX_ITERATIONS 10 int main() { double a, fa, fda; int i; בעיה: אנו נצטרך לכתוב תוכנית חדשה לכל פונקציה f. פתרון: שימוש בפונקציות ומצביעים לפונקציות (בהמשך הקורס). RUN scanf("%lf", &a); fa = a*a - 9; for(i = 0; i < MAX_ITERATIONS && (fa!= 0); ++i) { fa = a*a - 9; fda = 2*a; /* what if fda == 0? */ a = a - fa/fda; printf("iteration: %d, Solution: %.12f\n", i, a); printf("solution is: %.12f\n", a); return 0; 36 18